//===============================================================================
// Microsoft patterns & practices
// SharePoint Guidance
//===============================================================================
// Copyright (c) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using SPGSharePointDataAccessQuickStart.Common.Constants;
using SPGSharePointDataAccessQuickStart.Repository.BusinessEntities;
using SPGSharePointDataAccessQuickStart.Repository.SharePoint;

namespace SPGSharePointDataAccessQuickStart.Repository
{
    /// <summary>
    /// The BaseEntityRepositroy is the base class for all repository classes
    /// used for accessing lists in SharePoint. The base class is used to enforce
    /// the repository pattern for accessing lists in custom code. It abstracts
    /// the SharePoint calls from custom code.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class BaseEntityRepository<T> where T : BaseEntity, new()
    {
        #region Private Fields

        private IListItemRepository listItemRepository;

        #endregion

        #region Public Properties

        /// <summary>
        /// Derived classes must implement this property to
        /// indicate which list the repository is targeting.
        /// </summary>
        protected abstract string ListName
        {
            get;
        }

        #endregion

        #region Constructor

        protected BaseEntityRepository(IListItemRepository listItemRepository)
        {
            this.listItemRepository = listItemRepository;
        }

        #endregion

        #region Methods

        protected int AddListItem(T entity, SPWeb web)
        {
            Dictionary<Guid, object> fields = GatherParameters(entity, web);

            SPListItem item = null;

            item = listItemRepository.Add(web, this.ListName, fields);

            return (int)item[Fields.Id];
        }

        protected T GetListItem(string caml, SPWeb web)
        {
            T entity = null;

            SPQuery query = new SPQuery();
            query.Query = caml;

            SPListItem item = null;

            item = listItemRepository.Get(web, this.ListName, query);

            if ( item != null )
            {
                entity = PopulateEntity(item);
            }

            return entity;
        }

        protected void UpdateListItem(T entity, SPWeb web)
        {
            Dictionary<Guid, object> fields = GatherParameters(entity, web);

            listItemRepository.Update(web, this.ListName, entity.Id, fields);
        }

        protected void DeleteListItem(int id, SPWeb web)
        {
            listItemRepository.Delete(web, this.ListName, id);
        }

        public string GetFieldName(Guid key, SPWeb web)
        {
            return web.Lists[this.ListName].Fields[key].InternalName;
        }

        #region Abstract

        protected abstract Dictionary<Guid, object> GatherParameters(T entity, SPWeb web);
        protected abstract T PopulateEntity(SPListItem item);

        #endregion

        #endregion
    }
}
